trigger ProductsToReservationTrigger on OpportunityLineItem (after insert, after update, before delete) 
{
    if(Trigger.isUpdate || Trigger.isInsert)
    {
        Set<ID> oppProductOppIDList = new Set<ID>();
        MAP<ID, ID> productIDMap = new Map<ID, ID>();
        Map<ID, List<OpportunityLineItem>> oppToOLIMap = new Map<ID, List<OpportunityLineItem>>();
        Map<ID, List<Productivity_Allocations__c>> oppToPAMap = new Map<ID, List<Productivity_Allocations__c>>();
        MAP<ID, ID> oliToproductIDMap = new Map<ID, ID>();
        List<Reservations__c> reservationsList = new List<Reservations__c>();
        set<Reservations__c> reservationsSet1 = new Set<Reservations__c>();
        set<Reservations__c> reservationsSet2 = new Set<Reservations__c>();
        set<Reservations__c> reservationsSet3 = new Set<Reservations__c>();
        set<Reservations__c> reservationsSet4 = new Set<Reservations__c>();
        
        List<OpportunityLineItem> oldMapOLIList = new List<OpportunityLineItem>();
        
        if(Trigger.isUpdate)
        {
            oldMapOLIList = Trigger.oldMap.values();
        }
    
        List<OpportunityLineItem> oliTriggeredList = [select id, opportunityid, pricebookentry.product2.id, Added_Value__c, End__c, Flex__c, Description, ListPrice, make_good__c, servicedate, UnitPrice, quantity, start__c, TotalPrice from opportunitylineitem where id in :Trigger.new];    
        for(OpportunityLineItem oli: oliTriggeredList)
        {
           oppProductOppIDList.add(oli.Opportunityid);
           oliToproductIDMap.put(oli.id, oli.pricebookentry.product2.id);
        }
        
        for(OpportunityLineItem oli: oliTriggeredList)
        {
            List<OpportunityLineItem> oliList = oppToOLIMap.get(oli.opportunityid);
            if(oliList != null)
                oliList.add(oli);
            else
            {
                oliList = new List<OpportunityLineItem>();
                oliList.add(oli);
            }
            oppToOLIMap.put(oli.opportunityid, oliList);   
        }
    
        Map<ID, Productivity_Allocations__c> paMap = new Map<ID, Productivity_Allocations__c>([select id, Opportunity_Name__c, (select id, Added_Value__c, End__c, Flex__c, Line_Description__c, List_Price__c, Make_Good__c, Opportunity_Product__c, Opportunity_Product_Date__c, Opportunity_Product_Sales_Price__c, Quantity__c, Start__c, Total_Price__c from Reservations__r) from Productivity_Allocations__c where opportunity_name__c in :oppProductOppIDList]);
        for(Productivity_Allocations__c pa: paMap.values())
        {
            List<Productivity_Allocations__c> paList = oppToPAMap.get(pa.opportunity_name__c);
            if(paList != null)
                paList.add(pa);
            else
            {
                paList = new List<Productivity_Allocations__c>();
                paList.add(pa);
            }
            oppToPAMap.put(pa.opportunity_name__c, palist);   
        }
    
        
        for(ID oppId: oppToOliMap.keyset())
        {
            OpportunityLineItem[] oliListTemp = oppToOliMap.get(oppId);
            Productivity_Allocations__c[] paListTemp = oppToPAMap.get(oppId);
            Boolean flag = false;
            for(OpportunityLineItem oli: oliListTemp)
            {
                if(paListTemp != null)
                {            
                    for(Productivity_Allocations__c pa: paListTemp)
                    {
                        system.debug('Entered in for loop');
                        if(pa.reservations__r.size() == 0)
                        {
                            system.debug('Entered in Zero ');
                            Reservations__c r = new Reservations__c(Related_Productivity_Allocation__c = pa.id, Added_Value__c = oli.Added_Value__c, End__c = oli.End__c, Flex__c = oli.Flex__c, Line_Description__c = oli.Description, List_Price__c= oli.ListPrice, Make_Good__c = oli.make_good__c, Opportunity_Product_Date__c = oli.servicedate, Opportunity_Product_Sales_Price__c = oli.UnitPrice, Quantity__c = oli.quantity, Start__c = oli.start__c, Total_Price__c = oli.TotalPrice, Opportunity_Product__c = oli.pricebookentry.product2.id);
                            if(!reservationsSet1.contains(r))
                                reservationsSet1.add(r);
                            else if(!reservationsSet2.contains(r))
                            {
                                reservationsSet2.add(r);
                            }
                            else if(!reservationsSet3.contains(r))
                            {
                                reservationsSet3.add(r);
                            }
                            else if(!reservationsSet4.contains(r))
                            {
                                reservationsSet4.add(r);
                            }
                            
                        }
                        for(Reservations__c r: pa.Reservations__r)
                        {
                            flag = false;           
                            if(Trigger.oldMap != null)
                            {
                                OpportunityLineItem oliT = trigger.oldMap.get(oli.id);
                                if(r.Added_Value__c == oliT.Added_Value__c && r.total_price__c == oliT.TotalPrice && r.Quantity__c == oliT.quantity && r.opportunity_product_sales_price__c == oliT.Unitprice && r.Opportunity_Product_Date__c == oliT.ServiceDate && r.Make_Good__c == oliT.Make_Good__c && r.List_Price__c == oliT.ListPrice && r.Start__c == oliT.Start__c && r.End__c == oliT.End__c && r.Flex__c == oliT.Flex__c && r.Line_Description__c == oliT.Description)
                                {
                                    opportunitylineitem oliNew = Trigger.newMap.get(oli.id);
            
                                    r.Added_Value__c = oliNew.Added_Value__c;
                                    r.End__c = oliNew.End__c;
                                    r.Start__c = oliNew.Start__c;
                                    r.Make_good__c = oliNew.Make_good__c;
                                    r.Flex__c = oliNew.Flex__c;
                                    r.Line_Description__c = oliNew.Description;
                                    r.List_Price__c= oliNew.ListPrice;
                                    r.Opportunity_Product_Date__c = oliNew.servicedate;
                                    r.Opportunity_Product_Sales_Price__c = oliNew.UnitPrice;
                                    r.Quantity__c = oliNew.quantity;
                                    r.Total_Price__c = oliNew.TotalPrice;    
            
                                    if(!reservationsSet1.contains(r))
                                        reservationsSet1.add(r);
                                    else if(!reservationsSet2.contains(r))
                                    {
                                        reservationsSet2.add(r);
                                    }
                                    else if(!reservationsSet3.contains(r))
                                    {
                                        reservationsSet3.add(r);
                                    }
                                    else if(!reservationsSet4.contains(r))
                                    {
                                        reservationsSet4.add(r);
                                    }
                                    flag = true;
                                    break;
                                }
                            }
                            reservationsList.clear();
                            if(reservationsSet1.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet1);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet1.clear();
                            }
                            if(reservationsSet2.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet2);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet2.clear();
                            }
                            if(reservationsSet3.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet3);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet3.clear();
                            }
                            if(reservationsSet4.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet4);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet4.clear();
                            }
                        }
                        if(!flag && pa.Reservations__r.size() != 0)
                        {
                            opportunitylineitem oliNew = Trigger.newMap.get(oli.id);
                            Id productId = oliToproductIDMap.get(oli.id);
                            Reservations__c r = new Reservations__c(Related_Productivity_Allocation__c = pa.id, Added_Value__c = oliNew.Added_Value__c, End__c = oliNew.End__c, Flex__c = oliNew.Flex__c, Line_Description__c = oliNew.Description, List_Price__c= oliNew.ListPrice, Make_Good__c = oliNew.make_good__c, Opportunity_Product_Date__c = oliNew.servicedate, Opportunity_Product_Sales_Price__c = oliNew.UnitPrice, Quantity__c = oliNew.quantity, Start__c = oliNew.start__c, Total_Price__c = oliNew.TotalPrice, Opportunity_Product__c = productId);
                            if(!reservationsSet1.contains(r))
                                reservationsSet1.add(r);
                            else if(!reservationsSet2.contains(r))
                            {
                                reservationsSet2.add(r);
                            }
                            else if(!reservationsSet3.contains(r))
                            {
                                reservationsSet3.add(r);
                            }
                            else if(!reservationsSet4.contains(r))
                            {
                                reservationsSet4.add(r);
                            }
    
                            reservationsList.clear();
                            if(reservationsSet1.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet1);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet1.clear();
                            }
                            if(reservationsSet2.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet2);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet2.clear();
                            }
                            if(reservationsSet3.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet3);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet3.clear();
                            }
                            if(reservationsSet4.size() == 1000)
                            {
                                reservationsList.addAll(reservationsSet4);
                                upsert reservationsList;
                                reservationsList.clear();
                                reservationsSet4.clear();
                            }
                        }
                    }
                    
                }
            }
        }

        reservationsList.clear();
        reservationsList.addAll(reservationsSet1);
        upsert reservationsList;
        reservationsList.clear();
        reservationsSet1.clear();
        reservationsList.addAll(reservationsSet2);
        upsert reservationsList;
        reservationsList.clear();
        reservationsSet2.clear();
        reservationsList.addAll(reservationsSet3);
        upsert reservationsList;
        reservationsList.clear();
        reservationsSet3.clear();
        reservationsList.addAll(reservationsSet4);
        upsert reservationsList;
        reservationsList.clear();
        reservationsSet4.clear();
    }
    if(Trigger.isDelete)
    {
        Map<ID, Reservations__c> checkBeforeDeleteMap = new Map<ID, Reservations__c>();
        List<OpportunityLineItem> oliDeletedTriggeredList = [select id, opportunityid, pricebookentry.product2.id, Added_Value__c, End__c, Flex__c, Description, ListPrice, make_good__c, servicedate, UnitPrice, quantity, start__c, TotalPrice from opportunitylineitem where id in :Trigger.old];    
        List<ID> opportunityIdList = new List<ID>();
        Set<ID> opportunityProductIDList = new Set<ID>();
        for(OpportunityLineItem oli: oliDeletedTriggeredList)
        {
            opportunityIdList.add(oli.opportunityid);
            opportunityProductIDList.add(oli.pricebookentry.product2.id);
        }
        
        Reservations__c[] rList = [select id, Opportunity_Product__c, Added_Value__c, End__c, Start__c, Make_good__c, Flex__c, Line_Description__c, List_Price__c, Opportunity_Product_Date__c, Opportunity_Product_Sales_Price__c, Quantity__c, Total_Price__c, Related_Productivity_Allocation__c from Reservations__c where Related_Productivity_Allocation__r.opportunity_name__c in :opportunityIdList ];
        Map<ID, Reservations__c> delReservationsMap = new Map<ID, Reservations__c>();
        reservations__c rsCheck = null;
        for(OpportunityLineItem oliT: oliDeletedTriggeredList)
        {
            for(Reservations__c r: rList)
            {
                if(oliT.pricebookentry.product2.id == r.Opportunity_Product__c && r.Added_Value__c == oliT.Added_Value__c && r.total_price__c == oliT.TotalPrice && r.Quantity__c == oliT.quantity && r.opportunity_product_sales_price__c == oliT.Unitprice && r.Opportunity_Product_Date__c == oliT.ServiceDate && r.Make_Good__c == oliT.Make_Good__c && r.List_Price__c == oliT.ListPrice && r.Start__c == oliT.Start__c && r.End__c == oliT.End__c && r.Flex__c == oliT.Flex__c && r.Line_Description__c == oliT.Description)        
                {
                    if(checkBeforeDeleteMap.get(r.Related_Productivity_Allocation__c) != null)
                    {
                        rsCheck = checkBeforeDeleteMap.get(r.Related_Productivity_Allocation__c);
                    }    
                    else
                    {
                        rsCheck = r;
                        checkBeforeDeleteMap.clear();
                        checkBeforeDeleteMap.put(r.Related_Productivity_Allocation__c, r);
                        delReservationsMap.put(r.id, r);
                    }
                    if(rsCheck.Opportunity_Product__c != r.Opportunity_Product__c && r.Added_Value__c != rsCheck.Added_Value__c && r.total_price__c != rsCheck.total_price__c && r.Quantity__c != rsCheck.quantity__c && r.opportunity_product_sales_price__c != rsCheck.opportunity_product_sales_price__c && r.Opportunity_Product_Date__c != rsCheck.Opportunity_Product_Date__c && r.Make_Good__c != rsCheck.Make_Good__c && r.List_Price__c != rsCheck.list_price__c && r.Start__c != rsCheck.Start__c && r.End__c != rsCheck.End__c && r.Flex__c != rsCheck.Flex__c && r.Line_Description__c != rsCheck.Line_Description__c)                                        
                        delReservationsMap.put(r.id, r);
                }
            }
        }        
        delete delReservationsMap.values();
    }

}